package com.imooc.demo.common.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @className: DateUtils
 * @description: 日期工具类
 * @date: 2020/8/18
 * @author: cakin
 */
public class DateUtils {

    /**
     * 获取两个日期之间的日期
     *
     * @param start 开始日期
     * @param end   结束日期
     * @return 日期集合
     */
    public List<Date> getBetweenDates(Date start, Date end) {
        List<Date> result = new ArrayList<Date>();
        Calendar tempStart = Calendar.getInstance();
        tempStart.setTime(start);
        tempStart.add(Calendar.DAY_OF_YEAR, 1);
        Calendar tempEnd = Calendar.getInstance();
        tempEnd.setTime(end);
        while (tempStart.before(tempEnd)) {
            result.add(tempStart.getTime());
            tempStart.add(Calendar.DAY_OF_YEAR, 1);
        }
        return result;
    }

    /**
     * 获取某月的日期集合
     *
     * @param month 月份 2020-12
     * @return 日期集合
     * @throws ParseException
     */
    public String getMonthDates(String month) throws ParseException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
        Date date = format.parse(month);
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        int d = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        String dates = "";
        for (int i = 1; i <= d; i++) {
            if (i < 10) {
                dates += (month + "-0" + i + ",");
            } else {
                dates += (month + "-" + i + ",");
            }
        }
        dates = dates.substring(0, dates.length() - 1);
        return dates;
    }

    /**
     * 获取上个月的月份
     *
     * @return String 上个月的月份
     */
    public static String getPreMonth() {
        Calendar c = Calendar.getInstance();
        c.setTime(new Date());
        c.add(Calendar.MONTH, -1);
        Date m = c.getTime();
        return DateUtils.formatYYYYMM(m);
    }

    /**
     * 获取月的开始和结束时间
     *
     * @param date 日期
     * @return List<String> 时间列表
     */
    public static List<String> getMonthStartAndEnd(Date date) {
        List<String> dates = new ArrayList<>();
        Calendar cale = null;
        cale = Calendar.getInstance();
        cale.setTime(date);
        // 获取当月第一天和最后一天
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String firstDay, lastDay;
        // 获取前月的第一天
        cale = Calendar.getInstance();
        cale.setTime(date);
        cale.add(Calendar.MONTH, 0);
        cale.set(Calendar.DAY_OF_MONTH, 1);
        firstDay = format.format(cale.getTime());
        // 获取前月的最后一天
        cale = Calendar.getInstance();
        cale.setTime(date);
        cale.add(Calendar.MONTH, 1);
        cale.set(Calendar.DAY_OF_MONTH, 0);
        lastDay = format.format(cale.getTime());
        dates.add(firstDay);
        dates.add(lastDay);
        return dates;
    }

    /**
     * 获取一周的开始和结束时间
     *
     * @param date 日期
     * @return List<String> 时间列表
     */
    public static List<String> getWeekStartAndEnd(Date date) {
        List<String> list = new ArrayList<>();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        // 判断要计算的日期是否是周日，如果是则减一天计算周六的，否则会出问题，计算到下一周去了
        int dayWeek = cal.get(Calendar.DAY_OF_WEEK);// 获得当前日期是一个星期的第几天
        if (1 == dayWeek) {
            cal.add(Calendar.DAY_OF_MONTH, -1);
        }
        cal.setFirstDayOfWeek(Calendar.MONDAY);// 设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
        int day = cal.get(Calendar.DAY_OF_WEEK);// 获得当前日期是一个星期的第几天
        cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - day);// 根据日历的规则，给当前日期减去星期几与一个星期第一天的差值
        String firstTime, lastTime;
        firstTime = format.format(cal.getTime());// 获取一周的第一天
        cal.add(Calendar.DATE, 6);
        lastTime = format.format(cal.getTime());// 获取一周的最后一天
        list.add(firstTime);
        list.add(lastTime);
        return list;
    }

    /**
     * 获取季度的开始和结束时间
     *
     * @param date 日期
     * @return List<String> 时间列表
     */
    public static List<String> getQuarterStartAndEnd(Date date) {
        List<String> list = new ArrayList<>();
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        int currentMonth = c.get(Calendar.MONTH) + 1;
        try {
            if (currentMonth >= 1 && currentMonth <= 3)
                c.set(Calendar.MONTH, 0);
            else if (currentMonth >= 4 && currentMonth <= 6)
                c.set(Calendar.MONTH, 3);
            else if (currentMonth >= 7 && currentMonth <= 9)
                c.set(Calendar.MONTH, 6);
            else if (currentMonth >= 10 && currentMonth <= 12)
                c.set(Calendar.MONTH, 9);
            c.set(Calendar.DATE, 1);
            list.add(format.format(c.getTime()));
            //结束时间
            c.setTime(date);
            currentMonth = c.get(Calendar.MONTH) + 1;
            if (currentMonth >= 1 && currentMonth <= 3) {
                c.set(Calendar.MONTH, 2);
                c.set(Calendar.DATE, 31);
            } else if (currentMonth >= 4 && currentMonth <= 6) {
                c.set(Calendar.MONTH, 5);
                c.set(Calendar.DATE, 30);
            } else if (currentMonth >= 7 && currentMonth <= 9) {
                c.set(Calendar.MONTH, 8);
                c.set(Calendar.DATE, 30);
            } else if (currentMonth >= 10 && currentMonth <= 12) {
                c.set(Calendar.MONTH, 11);
                c.set(Calendar.DATE, 31);
            }
            list.add(format.format(c.getTime()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }


    /**
     * 格式化日期为指定格式的字符串
     *
     * @param time 日期时间
     * @return String 字符串时间
     */
    public static String formatLongYYYYMMDDHHMMSSSSS(Date time) {
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        return format.format(time);
    }

    /**
     * 格式化日期为指定格式的字符串
     *
     * @param time 日期时间
     * @return String 字符串时间
     */
    public static String formatLongYYYYMMDDHHMMSS(Date time) {
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        return format.format(time);
    }


    /**
     * 格式化日期为指定格式的字符串
     *
     * @param time 日期时间
     * @return String 字符串时间
     */
    public static String formatLongYYMMDDHHMMSS(Date time) {
        SimpleDateFormat format = new SimpleDateFormat("yyMMddHHmmss");
        return format.format(time);
    }

    /**
     * 格式化日期为指定格式的字符串
     *
     * @param time 日期时间
     * @return String 字符串时间
     */
    public static String formatYYYYMMDDHHMMSS(Date time) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return format.format(time);
    }

    /**
     * 格式化日期为指定格式的字符串
     *
     * @param time 日期时间
     * @return String 字符串时间
     */
    public static String formatYYYYMMDD(Date time) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        return format.format(time);
    }

    /**
     * 格式化日期为指定格式的字符串
     *
     * @param time 日期时间
     * @return String 字符串时间
     */
    public static String formatYYYYMM(Date time) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
        return format.format(time);
    }

    /**
     * 格式化日期为指定格式的字符串
     *
     * @param time 日期时间
     * @return String 字符串时间
     */
    public static String formatYYYYMM_CN(Date time) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月");
        return format.format(time);
    }

    /**
     * 格式化日期为指定格式的字符串
     *
     * @param time 日期时间
     * @return String 字符串时间
     */
    public static String formatYYYY(Date time) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy");
        return format.format(time);
    }

    /**
     * 格式化日期为指定格式的字符串
     *
     * @param time 日期时间
     * @return String 字符串时间
     */
    public static String formatMM(Date time) {
        SimpleDateFormat format = new SimpleDateFormat("MM");
        return format.format(time);
    }

    /**
     * 将对应格式的字符串转换为日期类型
     *
     * @param time 字符串时间 2020-08-18 15:04:17
     * @return Date 日期时间
     */
    public static Date formatYYYYMMDDHHMMSS(String time) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            return format.parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 将对应格式的字符串转换为日期类型
     *
     * @param time 字符串时间 2020-08-18
     * @return Date 日期时间
     */
    public static Date formatYYYYMMDD(String time) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        try {
            return format.parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
            throw new RuntimeException("日期格式有误，正确格式为yyyy-MM-dd");
        }
    }

    /**
     * 将对应格式的字符串转换为日期类型
     *
     * @param time 字符串时间 2020-08-18
     * @return Date 日期时间
     */
    public static Date formatYYYYMM(String time) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
        try {
            return format.parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 根据日期获取是周几
     *
     * @param time 日期时间
     * @return int 周几
     * @throws Throwable
     */
    public static int dayForWeek(Date time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        int intWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1;
        return intWeek;
    }

    /**
     * 获取指定年的最后一天
     *
     * @param year 年份
     * @return Date 日期
     */
    public static Date getYearLastDay(int year) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.roll(Calendar.DAY_OF_YEAR, -1);
        Date currYearLast = calendar.getTime();
        return currYearLast;
    }

    public static void main(String[] args) throws ParseException {
        // getBetweenDates 测试
        DateUtils dateUtils = new DateUtils();
        List<Date> betweenDates = dateUtils.getBetweenDates(new Date(500000), new Date(600000000));
        for (Date betweenDate : betweenDates) {
            System.out.println(betweenDate.toString());
        }
        System.out.println("++++++++++++++++++++++++++++++++++");
        // getMonthDates 测试
        String monthDates = dateUtils.getMonthDates("2020-07");
        System.out.println(monthDates);
        System.out.println("++++++++++++++++++++++++++++++++++");
        // getPreMonth 测试
        String preMonth = dateUtils.getPreMonth();
        System.out.println(preMonth);
        System.out.println("++++++++++++++++++++++++++++++++++");
        // getMonthStartAndEnd 测试
        List<String> monthStartAndEnd = DateUtils.getMonthStartAndEnd(new Date());
        for (int i = 0; i < monthStartAndEnd.size(); i++) {
            System.out.println(monthStartAndEnd.get(i));
        }
        System.out.println("++++++++++++++++++++++++++++++++++");
        // getWeekStartAndEnd 测试
        List<String> weekStartAndEnd = DateUtils.getWeekStartAndEnd(new Date());
        for (int i = 0; i < weekStartAndEnd.size(); i++) {
            System.out.println(weekStartAndEnd.get(i));
        }
        System.out.println("++++++++++++++++++++++++++++++++++");
        // getQuarterStartAndEnd 测试
        List<String> quarterStartAndEnd = DateUtils.getQuarterStartAndEnd(new Date());
        for (int i = 0; i < quarterStartAndEnd.size(); i++) {
            System.out.println(quarterStartAndEnd.get(i));
        }
        System.out.println("++++++++++++++++++++++++++++++++++");
        // formatLongYYYYMMDDHHMMSSSSS 测试
        String s = DateUtils.formatLongYYYYMMDDHHMMSSSSS(new Date());
        System.out.println(s);
        System.out.println("++++++++++++++++++++++++++++++++++");
        // formatLongYYYYMMDDHHMMSS 测试
        String s1 = DateUtils.formatLongYYYYMMDDHHMMSS(new Date());
        System.out.println(s1);
        System.out.println("++++++++++++++++++++++++++++++++++");
        // formatLongYYMMDDHHMMSS 测试
        String s2 = DateUtils.formatLongYYMMDDHHMMSS(new Date());
        System.out.println(s2);
        System.out.println("++++++++++++++++++++++++++++++++++");
        // formatYYYYMMDDHHMMSS 测试
        String s3 = DateUtils.formatYYYYMMDDHHMMSS(new Date());
        System.out.println(s3);
        System.out.println("++++++++++++++++++++++++++++++++++");
        // formatYYYYMMDD 测试
        String s4 = DateUtils.formatYYYYMMDD(new Date());
        System.out.println(s4);
        System.out.println("++++++++++++++++++++++++++++++++++");
        // formatYYYYMM 测试
        String s5 = DateUtils.formatYYYYMM(new Date());
        System.out.println(s5);
        System.out.println("++++++++++++++++++++++++++++++++++");
        // formatYYYYMM_CN 测试
        String s6 = DateUtils.formatYYYYMM_CN(new Date());
        System.out.println(s6);
        System.out.println("++++++++++++++++++++++++++++++++++");
        // formatYYYY 测试
        String s7 = DateUtils.formatYYYY(new Date());
        System.out.println(s7);
        System.out.println("++++++++++++++++++++++++++++++++++");
        // formatMM 测试
        String s8 = DateUtils.formatMM(new Date());
        System.out.println(s8);
        System.out.println("++++++++++++++++++++++++++++++++++");
        // formatYYYYMMDDHHMMSS 测试
        Date date = DateUtils.formatYYYYMMDDHHMMSS("2020-08-18 15:04:17");
        System.out.println(date.toString());
        System.out.println("++++++++++++++++++++++++++++++++++");
        // formatYYYYMMDD 测试
        Date date1 = DateUtils.formatYYYYMMDD("2020-08-18");
        System.out.println(date1.toString());
        System.out.println("++++++++++++++++++++++++++++++++++");
        // formatYYYYMM 测试
        Date date2 = DateUtils.formatYYYYMM("2020-08");
        System.out.println(date2.toString());
        System.out.println("++++++++++++++++++++++++++++++++++");
        // dayForWeek 测试
        int i = DateUtils.dayForWeek(new Date());
        System.out.println(i);
        System.out.println("++++++++++++++++++++++++++++++++++");
        // getYearLastDay 测试
        Date yearLastDay = DateUtils.getYearLastDay(2020);
        System.out.println(yearLastDay.toLocaleString());
    }
}
